﻿using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace LJ.Abstractions.Extensions;

public static class TypeExtensions
{
    /// <summary>
    /// 判断当前类型是否可由指定类型派生
    /// </summary>
    public static bool IsDeriveClassFrom<TBaseType>(this Type type, bool canAbstract = false)
    {
        return type.IsDeriveClassFrom(typeof(TBaseType), canAbstract);
    }

    /// <summary>
    /// 判断当前类型是否可由指定类型派生
    /// </summary>
    public static bool IsDeriveClassFrom(this Type type, Type baseType, bool canAbstract = false)
    {

        return type.IsClass && (canAbstract || !type.IsAbstract) && type.IsBaseOn(baseType);
    }
    /// <summary>
    /// 返回当前类型是否是指定基类的派生类
    /// </summary>
    /// <param name="type">当前类型</param>
    /// <param name="baseType">要判断的基类型</param>
    /// <returns></returns>
    public static bool IsBaseOn(this Type type, Type baseType)
    {
        if (baseType.IsGenericTypeDefinition)
        {
            return baseType.IsGenericAssignableFrom(type);
        }
        return baseType.IsAssignableFrom(type);
    }

    /// <summary>
    /// 返回当前类型是否是指定基类的派生类
    /// </summary>
    /// <typeparam name="TBaseType">要判断的基类型</typeparam>
    /// <param name="type">当前类型</param>
    /// <returns></returns>
    public static bool IsBaseOn<TBaseType>(this Type type)
    {
        Type baseType = typeof(TBaseType);
        return type.IsBaseOn(baseType);
    }

    /// <summary>
    /// 判断当前泛型类型是否可由指定类型的实例填充
    /// </summary>
    /// <param name="genericType">泛型类型</param>
    /// <param name="type">指定类型</param>
    /// <returns></returns>
    public static bool IsGenericAssignableFrom(this Type genericType, Type type)
    {
        if (!genericType.IsGenericType)
        {
            throw new ArgumentException("该功能只支持泛型类型的调用，非泛型类型可使用 IsAssignableFrom 方法。");
        }

        List<Type> allOthers = [type];
        if (genericType.IsInterface)
        {
            allOthers.AddRange(type.GetInterfaces());
        }

        foreach (var other in allOthers)
        {
            var cur = other;
            while (cur != null)
            {
                if (cur.IsGenericType)
                {
                    cur = cur.GetGenericTypeDefinition();
                }
                if (cur.IsSubclassOf(genericType) || cur == genericType)
                {
                    return true;
                }
                cur = cur.BaseType;
            }
        }
        return false;
    }

    /// <summary>
    /// 获取方法真实返回类型
    /// </summary>
    /// <param name="method"></param>
    /// <returns></returns>
    public static Type GetRealReturnType(this MethodInfo method)
    {
        // 判断是否是异步方法
        var isAsyncMethod = method.IsAsync();

        // 获取类型返回值并处理 Task 和 Task<T> 类型返回值
        var returnType = method.ReturnType;
        return isAsyncMethod ? returnType.GenericTypeArguments.FirstOrDefault() ?? typeof(void) : returnType;
    }

    /// <summary>
    /// 判断方法是否是异步
    /// </summary>
    /// <param name="method">方法</param>
    /// <returns></returns>
    public static bool IsAsync(this MethodInfo method)
    {
        return method.GetCustomAttribute<AsyncMethodBuilderAttribute>() != null
            || method.ReturnType.ToString().StartsWith(typeof(Task).FullName!);
    }


   

    /// <summary>
    /// 判断是否是富基元类型
    /// </summary>
    /// <param name="type">类型</param>
    /// <returns></returns>
    public static bool IsRichPrimitive(this Type type)
    {
        // 处理元组类型
        if (type.IsValueTuple()) return false;

        // 处理数组类型，基元数组类型也可以是基元类型
        if (type.IsArray) return type.GetElementType()!.IsRichPrimitive();

        // 基元类型或值类型或字符串类型
        if (type.IsPrimitive || type.IsValueType || type == typeof(string)) return true;

        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) return type.GenericTypeArguments[0].IsRichPrimitive();

        return false;
    }


    /// <summary>
    /// 判断是否是元组类型
    /// </summary>
    /// <param name="type">类型</param>
    /// <returns></returns>
    public static bool IsValueTuple(this Type type)
    {
        return type.Namespace == "System" && type.Name.Contains("ValueTuple`");
    }

    /// <summary>
    /// 判断参数类型是不是原始类型，枚举和一些拓展类型
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsPrimitiveExtendedIncludingNullable(this Type type)
    {
        //是不是原始类型，枚举类型，和一些扩展类型
        if (IsPrimitiveExtended(type))
            return true;

        //是不是可空类型
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
            return IsPrimitiveExtended(type.GenericTypeArguments[0]);

        return false;
    }
    public static bool IsPrimitiveExtended(this Type type)
    {
        if (type.IsPrimitive || type.IsEnum)
            return true;

        return type == typeof(string) ||
               type == typeof(decimal) ||
               type == typeof(DateTime) ||
               type == typeof(DateTimeOffset) ||
               type == typeof(TimeSpan) ||
               type == typeof(Guid);
    }
}
